package com.syni.mdd.sjb.common.component.utils.common.utils;

import com.qcloud.cos.COSClient;
import com.qcloud.cos.ClientConfig;
import com.qcloud.cos.auth.BasicCOSCredentials;
import com.qcloud.cos.auth.COSCredentials;
import com.qcloud.cos.http.HttpProtocol;
import com.qcloud.cos.model.GetObjectRequest;
import com.qcloud.cos.model.ObjectMetadata;
import com.qcloud.cos.model.PutObjectRequest;
import com.qcloud.cos.model.PutObjectResult;
import com.qcloud.cos.region.Region;
import com.syni.mdd.sjb.common.component.utils.common.entity.BmsCdnData;
import com.tencent.cloud.CosStsClient;
import lombok.extern.log4j.Log4j2;
import net.coobird.thumbnailator.Thumbnails;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import sun.misc.BASE64Decoder;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Random;
import java.util.TreeMap;

@Log4j2
@Configuration
public class CDNUtils {

    private static long appId = 1251624226;
    private static String secretId = "AKIDWs1xfAxWN0PcfV5WhePwFKCqGSRCO4B5";
    private static String secretKey = "mLgojRvCG6i7IFzVnriLkvtd9RWN6btx";
    public static String bucketName = "dsp";
    public static final int width = 200;
    public static final int height = 200;

    @Value("${cdn.appid:1251624226}")
    public void setAppId(long appId) {
        CDNUtils.appId = appId;
    }

    @Value("${cdn.secretId:AKIDWs1xfAxWN0PcfV5WhePwFKCqGSRCO4B5}")
    public void setSecretId(String secretId) {
        CDNUtils.secretId = secretId;
    }

    @Value("${cdn.secretKey:mLgojRvCG6i7IFzVnriLkvtd9RWN6btx}")
    public void setSecretKey(String secretKey) {
        CDNUtils.secretKey = secretKey;
    }


    /**
     * @param bucketName (台风：typhoon,短视频：dsp)
     * @param cosPath    上传图片位置文件夹
     * @param loaclPath  本地图片地址
     * @param sWidth     压缩图宽
     * @param sHeight    压缩图高
     * @return
     */
    public static BmsCdnData uploadCOS(String bucketName, String cosPath, String localPath, int sWidth, int sHeight) {
        BmsCdnData cdnData = null;
        COSClient cosClient = null;
        try {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS");

            // 1 初始化用户身份信息（secretId, secretKey）。
            COSCredentials cred = new BasicCOSCredentials(secretId, secretKey);
            // 2 设置 bucket 的区域, COS 地域的简称请参照 https://cloud.tencent.com/document/product/436/6224
            // clientConfig 中包含了设置 region, https(默认 http), 超时, 代理等 set 方法, 使用可参见源码或者常见问题 Java SDK 部分。
            Region region = new Region("ap-guangzhou");
            ClientConfig clientConfig = new ClientConfig(region);
            // 3 生成 cos 客户端。
            cosClient = new COSClient(cred, clientConfig);
            String suffix = "." + localPath.substring(localPath.lastIndexOf(".") + 1);
            String imageName = sdf.format(new Date()) + getStringRandom(4);
            String bigImageName = "b" + imageName + suffix;
            String smallImageName =  "b" + imageName + "_s" + suffix;
            String bigImageResult = upload(bucketName + "-" + appId, cosPath + bigImageName, localPath, cosClient);
            String smallPath = compressByScan(localPath, smallImageName,0.5d);
            String smallImageResult = "";
            if(StringUtils.isNotBlank(smallPath)) {
                smallImageResult = upload(bucketName + "-" + appId, cosPath + smallImageName, smallPath, cosClient);
            }
            if (StringUtils.isNotBlank(bigImageResult)) {
                //System.err.print("上传成功原图url------>>>>" + bigImageResult);
                //System.err.print("上传成功缩略图url------>>>>" + smallImageResult);
                cdnData = new BmsCdnData();
                cdnData.setCosPath(cosPath);
                cdnData.setSourceUrlBig(bigImageResult);
                cdnData.setSourceUrlSmall(smallImageResult);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            cosClient.shutdown();
        }
        return cdnData;
    }

    /**
     * @param bucketName (台风：typhoon,短视频：dsp)
     * @param cosPath    上传图片位置文件夹
     * @param loaclPath  本地图片地址
     * @param sWidth     压缩图宽
     * @param sHeight    压缩图高
     * @return
     */
    public static BmsCdnData uploadCOS1(String bucketName, String cosPath, String localPath, int sWidth, int sHeight) {
        BmsCdnData cdnData = null;
        COSClient cosClient = null;
        try {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS");

            // 1 初始化用户身份信息（secretId, secretKey）。
            COSCredentials cred = new BasicCOSCredentials(secretId, secretKey);
            // 2 设置 bucket 的区域, COS 地域的简称请参照 https://cloud.tencent.com/document/product/436/6224
            // clientConfig 中包含了设置 region, https(默认 http), 超时, 代理等 set 方法, 使用可参见源码或者常见问题 Java SDK 部分。
            Region region = new Region("ap-guangzhou");
            ClientConfig clientConfig = new ClientConfig(region);
            clientConfig.setHttpProtocol(HttpProtocol.https);
            // 3 生成 cos 客户端。
            cosClient = new COSClient(cred, clientConfig);
            String suffix = "." + localPath.substring(localPath.lastIndexOf(".") + 1);
            String imageName = sdf.format(new Date()) + getStringRandom(4);
            String bigImageName = "index-functionlist-img1.png";
//            String smallImageName =  "b" + imageName + "_s" + suffix;
            String bigImageResult = upload(bucketName + "-" + appId, cosPath + bigImageName, localPath, cosClient);
//            String smallPath = compressByScan(localPath, smallImageName,0.5d);
            String smallImageResult = "";
//            if(StringUtils.isNotBlank(smallPath)) {
//                smallImageResult = upload(bucketName + "-" + appId, cosPath + smallImageName, smallPath, cosClient);
//            }
            if (StringUtils.isNotBlank(bigImageResult)) {
                //System.err.print("上传成功原图url------>>>>" + bigImageResult);
                //System.err.print("上传成功缩略图url------>>>>" + smallImageResult);
                cdnData = new BmsCdnData();
                cdnData.setCosPath(cosPath);
                cdnData.setSourceUrlBig(bigImageResult);
                cdnData.setSourceUrlSmall(smallImageResult);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            cosClient.shutdown();
        }
        return cdnData;
    }


    /**
     * @param bucketName (台风：typhoon,短视频：dsp)
     * @param cosPath    上传图片位置文件夹
     * @param loaclPath  本地图片地址
     * @param scale     压缩比例
     * @return
     */
    public static BmsCdnData uploadCOS(String bucketName, String cosPath, String loaclPath, Double scale) {
        BmsCdnData cdnData = null;
        COSClient cosClient = null;
        try {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS");

            // 1 初始化用户身份信息（secretId, secretKey）。
            COSCredentials cred = new BasicCOSCredentials(secretId, secretKey);
            // 2 设置 bucket 的区域, COS 地域的简称请参照 https://cloud.tencent.com/document/product/436/6224
            // clientConfig 中包含了设置 region, https(默认 http), 超时, 代理等 set 方法, 使用可参见源码或者常见问题 Java SDK 部分。
            Region region = new Region("ap-guangzhou");
            ClientConfig clientConfig = new ClientConfig(region);
            // 3 生成 cos 客户端。
            cosClient = new COSClient(cred, clientConfig);
            String suffix = "." + loaclPath.substring(loaclPath.lastIndexOf(".") + 1);
            String imageName = sdf.format(new Date()) + getStringRandom(4);
            String bigImageName = "b" + imageName + suffix;
            String smallImageName =  "b" + imageName + "_s" + suffix;
            String bigImageResult = upload(bucketName + "-" + appId, cosPath + bigImageName, loaclPath, cosClient);
            System.out.println("localPath: " + loaclPath);
            System.out.println("smallImage：" + smallImageName);
            String smallPath = compressByScan(loaclPath, smallImageName,scale);
            String smallImageResult = "";
            if(StringUtils.isNotBlank(smallPath)) {
                smallImageResult = upload(bucketName + "-" + appId, cosPath + smallImageName, smallPath, cosClient);
            }
            if (StringUtils.isNotBlank(bigImageResult)) {
                //System.err.print("上传成功原图url------>>>>" + bigImageResult);
                //System.err.print("上传成功缩略图url------>>>>" + smallImageResult);
                cdnData = new BmsCdnData();
                cdnData.setCosPath(cosPath);
                cdnData.setSourceUrlBig(bigImageResult);
                cdnData.setSourceUrlSmall(smallImageResult);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            cosClient.shutdown();
        }
        return cdnData;
    }

    public static void deleteCOS(String bucketName, String cosPath) {
      /*  DelFileRequest delFileRequest = new DelFileRequest(bucketName, cosPath);
        // 初始化密钥信息
        Credentials cred = new Credentials(appId, secretId, secretKey);
        // 初始化客户端配置
        ClientConfig clientConfig = new ClientConfig();
        // 设置bucket所在的区域，比如华南园区：gz； 华北园区：tj；华东园区：sh ；
        clientConfig.setRegion("gz");
        // 初始化cosClient
        COSClient cosClient = new COSClient(clientConfig, cred);
        String delFileRet = cosClient.delFile(delFileRequest);
        JSONObject jsonObject = JSONObject.parseObject(delFileRet);
        String code = jsonObject.getString("code");*/
//        JSONObject data = jsonObject.getJSONObject("data");
        // 1 初始化用户身份信息（secretId, secretKey）。
        COSCredentials cred = new BasicCOSCredentials(secretId, secretKey);
        // 2 设置 bucket 的区域, COS 地域的简称请参照 https://cloud.tencent.com/document/product/436/6224
        // clientConfig 中包含了设置 region, https(默认 http), 超时, 代理等 set 方法, 使用可参见源码或者常见问题 Java SDK 部分。
        Region region = new Region("ap-guangzhou");
        ClientConfig clientConfig = new ClientConfig(region);
        // 3 生成 cos 客户端。
        COSClient cosClient = new COSClient(cred, clientConfig);
        cosClient.deleteObject(bucketName + "-" + appId, cosPath);
        cosClient.shutdown();
    }

    /**
     * @Description 随机生成带数字和字母的数字随机数
     * @Author: cfx
     * @Date: 2019/7/3
     */
    public static String getStringRandom(int length) {
        StringBuilder val = new StringBuilder();
        Random random = new Random();
        //参数length，表示生成几位随机数
        for(int i = 0; i < length; i++) {
            String charOrNum = random.nextInt(2) % 2 == 0 ? "char" : "num";
            //输出字母还是数字
            if( "char".equalsIgnoreCase(charOrNum) ) {
                //输出是大写字母还是小写字母
                int temp = random.nextInt(2) % 2 == 0 ? 65 : 97;
                val.append((char)(random.nextInt(26) + temp));
            } else if( "num".equalsIgnoreCase(charOrNum) ) {
                val.append(String.valueOf(random.nextInt(10)));
            }
        }
        return val.toString();
    }


    public static String compress(String localPath, String fileName, int width, int height) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        String dateFile = sdf.format(new Date());
        File file = new File(localPath);
        File parentFile = file.getParentFile();
        String imgPath = parentFile.getAbsolutePath() + "/" + fileName;
        /*try {
            Thumbnails.of(localPath).size(width, height).toFile(imgPath);
            return imgPath;
        } catch (Exception e) {
            e.printStackTrace();
        }*/
        return null;
    }

    public static String compressByScan(String localPath, String fileName,Double scale) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        String dateFile = sdf.format(new Date());
        File file = new File(localPath);
        File parentFile = file.getParentFile();
        String imgPath = parentFile.getAbsolutePath() + "/" + fileName;
        try {
            Thumbnails.of(localPath).scale(scale).toFile(imgPath);
            return imgPath;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public static String upload(String bucketName, String cosPath, String localPath, COSClient cosClient) {
        // 指定要上传的文件
        File localFile = new File(localPath);
        // 指定要上传到 COS 上对象键
        String key = cosPath;
        PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, key, localFile);
        PutObjectResult putObjectResult = cosClient.putObject(putObjectRequest);
        String eTag = putObjectResult.getETag();
        if (null != eTag && !"".equals(eTag)) {
            //System.out.println(String.format("http://%s.cos.ap-guangzhou.myqcloud.com/%s",bucketName,key));
            //String url = "http://dsp.syni.com" + cosPath;
            String url = String.format("http://%s.cos.ap-guangzhou.myqcloud.com%s",bucketName,key);
            return url;
        }
        return "";
    }

    public static File downLoadCdnFile(String url) {
        String loaclPath = "D:/setting/img/中文图片.jpg";
        File downFile = new File(loaclPath);
        return downLoadCdnFile(url,downFile);
    }

    public static File downLoadCdnFile(String url,File downFile) {
        try {
            COSCredentials cred = new BasicCOSCredentials(AppConfig.getProperty("cloud.secret.id"), AppConfig.getProperty("cloud.secret.key"));
            ClientConfig clientConfig = new ClientConfig();
            Region region = new Region("ap-guangzhou");
            clientConfig.setRegion(region);

            COSClient cosClient = new COSClient(cred, clientConfig);
            // 指定对象所在的存储桶
            String bucketName = "dsp-" + appId;
            // 指定对象在 COS 上的对象键
            //先尝试找小的
            String[] cute = url.split("com");
            String key = cute[1];
            // 指定要下载到的本地路径
            GetObjectRequest getObjectRequest = new GetObjectRequest(bucketName, key);
            ObjectMetadata downObjectMeta = cosClient.getObject(getObjectRequest, downFile);
            return downFile;
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }

    public static boolean httpDownload(String httpUrl, String saveFile) {
        // 1.下载网络文件
        int byteRead;
        URL url;
        try {
            url = new URL(httpUrl);
        } catch (MalformedURLException e1) {
            e1.printStackTrace();
            return false;
        }

        try {
            //2.获取链接
            URLConnection conn = url.openConnection();
            //3.输入流
            InputStream inStream = conn.getInputStream();
            //3.写入文件
            FileOutputStream fs = new FileOutputStream(saveFile);

            byte[] buffer = new byte[1024];
            while ((byteRead = inStream.read(buffer)) != -1) {
                fs.write(buffer, 0, byteRead);
            }
            inStream.close();
            fs.close();
            return true;
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            return false;
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }
    }


    public static HttpServletResponse flushToChomd(File file, HttpServletResponse response) {
        try {
            // 取得文件名。
            String filename = file.getName();
            // 取得文件的后缀名。
            String ext = filename.substring(filename.lastIndexOf(".") + 1).toUpperCase();

            // 以流的形式下载文件。
            InputStream fis = new BufferedInputStream(new FileInputStream(file));
            byte[] buffer = new byte[fis.available()];
            fis.read(buffer);
            fis.close();
            // 清空response
            response.reset();
            // 设置response的Header
            response.addHeader("Content-Disposition", "attachment;filename=" + new String(filename.getBytes(),"ISO8859-1"));
            response.addHeader("Content-Length", "" + file.length());
            OutputStream toClient = new BufferedOutputStream(response.getOutputStream());
            response.setContentType("application/octet-stream");
            toClient.write(buffer);
            toClient.flush();
            toClient.close();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
        return response;
    }

    /**
     44      * base64字符串转化成图片
     45      *
     46      * @param imgData
     47      *            图片编码
     48      * @param imgFilePath
     49      *            存放到本地路径
     50      * @return
     51      * @throws IOException
     52      */
    public static boolean generateImage(String imgData, String imgFilePath) { // 对字节数组字符串进行Base64解码并生成图片
        if (imgData == null) // 图像数据为空
            return false;
        BASE64Decoder decoder = new BASE64Decoder();
        OutputStream out = null;
        try {
            out = new FileOutputStream(imgFilePath);
            // Base64解码
            byte[] b = decoder.decodeBuffer(imgData);
            for (int i = 0; i < b.length; ++i) {
                if (b[i] < 0) {// 调整异常数据
                    b[i] += 256;
                }
            }
            out.write(b);
            return true;
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            log.error(e.getMessage(),e);
        } catch (IOException e) {
            log.error(e.getMessage(),e);
        } finally {
            try {
                out.flush();
                out.close();
            } catch (IOException e) {
                log.error(e.getMessage(),e);
            }
        }
        return false;
    }

    public static JSONObject getUploadSignature() {

        TreeMap<String, Object> config = new TreeMap<String, Object>();
        JSONObject credential = new JSONObject();
        try {
            // 替换为您的 SecretId
            config.put("SecretId", secretId);
            // 替换为您的 SecretKey
            config.put("SecretKey", secretKey);

            // 临时密钥有效时长，单位是秒，默认1800秒，目前主账号最长2小时（即7200秒），子账号最长36小时（即129600秒）
            config.put("durationSeconds", 1800);

            // 换成您的 bucket
            config.put("bucket", bucketName + "-" + appId);
            // 换成 bucket 所在地区
            config.put("region", "ap-guangzhou");

            // 这里改成允许的路径前缀，可以根据自己网站的用户登录态判断允许上传的具体路径，例子：a.jpg 或者 a/* 或者 * 。
            // 如果填写了“*”，将允许用户访问所有资源；除非业务需要，否则请按照最小权限原则授予用户相应的访问权限范围。
            config.put("allowPrefix", "a.jpg");

            // 密钥的权限列表。简单上传、表单上传和分片上传需要以下的权限，其他权限列表请看 https://cloud.tencent.com/document/product/436/31923
            String[] allowActions = new String[] {
                    // 简单上传
                    "name/cos:PutObject",
                    // 表单上传、小程序上传
                    "name/cos:PostObject",
                    // 分片上传
                    "name/cos:InitiateMultipartUpload",
                    "name/cos:ListMultipartUploads",
                    "name/cos:ListParts",
                    "name/cos:UploadPart",
                    "name/cos:CompleteMultipartUpload"
            };
            config.put("allowActions", allowActions);
            credential = CosStsClient.getCredential(config);
        } catch (Exception e) {
            //失败抛出异常
            throw new IllegalArgumentException("no valid secret !");
        }
        return credential;
    }
}
